﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;

using FRL.DebtChased.ServiceUtilities;
using FRL.DebtChased.Repository;

namespace FRL.DebtChased.ClockworkService
{

	/// <summary>
	/// Declaration of ClockworkService class
	/// </summary>
	public partial class ClockworkService : ServiceBase
	{

		/////////////////////////////////////////////////////////////
		// Constants and enumerations

		private const int NEW_ACCOUNT = 0;
		private const int WORKFLOW = 1;
		private const int MESSAGING = 2;
		private const int WORKER_COUNT = 3;

		/////////////////////////////////////////////////////////////
		// Attributes

		private BaseWorker[] m_workerArray;

		/////////////////////////////////////////////////////////////
		// Construction

		public ClockworkService()
		{

			// Initialize resources
			InitializeComponent();

			// Update log file
			LogFile.Append("ClockworkService: constructor");

			// Create the worker objects
			m_workerArray = new BaseWorker[WORKER_COUNT];
			m_workerArray[NEW_ACCOUNT] = new NewAccountWorker();
			m_workerArray[WORKFLOW] = new WorkflowWorker();
			m_workerArray[MESSAGING] = new MessagingWorker();

		}

		/////////////////////////////////////////////////////////////
		// Event Handlers

		protected override void OnStart(string[] args)
		{

			// Update log file
			LogFile.Append("ClockworkService: OnStartAll");

			// Start the worker threads
			StartAllThreads();

		}

		protected override void OnStop()
		{

			// Update log file
			LogFile.Append("ClockworkService: OnStopAll");

			// Stop the worker threads
			StopAllThreads();

		}

		/////////////////////////////////////////////////////////////
		// Operations

		public bool StartAllThreads()
		{

			// Declare return variable
			bool bFtmp = true;

			// Check the database connection
			try
			{

				// Loop through the worker threads
				for(int i1=0; i1<WORKER_COUNT; i1++ )
				{

					// Start the thread
					if(!_startWorker(i1,true))
					{

						// Update return variable and break
						bFtmp = false;
						break;

					}

				}

			}
			catch (Exception x)
			{

				// Log the error
				LogFile.Append(string.Format("Failed to start service.  {0}",Definitions.SeeErrorLog));
				LogFile.Append(x);

				// Update return variable
				bFtmp = false;

			}

			// Return variable
			return bFtmp;

		}

		public void StopAllThreads()
		{

			// Loop through the worker threads
			for (int i1 = 0; i1 < WORKER_COUNT; i1++)
			{
				if (m_workerArray[i1].IsBusy)
					_startWorker(i1, false);
			}

		}

		public void StartNewAccountThread( bool bStart ) { _startWorker(NEW_ACCOUNT,bStart); }
		public void StartWorkflowThread( bool bStart ) { _startWorker(WORKFLOW,bStart); }
		public void StartMessagingThread( bool bStart ) { _startWorker(MESSAGING,bStart); }

		private bool _startWorker(int iThreadIndex, bool bStart)
		{
#if DEBUG
			Debug.Assert(iThreadIndex >= 0);
			Debug.Assert(iThreadIndex < WORKER_COUNT);
#endif // #if DEBUG

			// Declare return variable
			bool bFtmp = true;

			try
			{

				// If starting the thread...
				if(bStart)
				{

					// Try and start the thread
					if (!m_workerArray[iThreadIndex].IsBusy)
						m_workerArray[iThreadIndex].Start();
					else
						Console.WriteLine("Thread already running.");

				}
				else
				{

					// Try and stop the thread
					if(m_workerArray[iThreadIndex].IsBusy)
						m_workerArray[iThreadIndex].Stop();
					else
						Console.WriteLine("Thread already stopped.");

				}

			}
			catch(Exception x)
			{

				// Log the error
				LogFile.Append(string.Format("Failed to {0} new-account worker.", bStart?"start":"stop"));
				LogFile.Append(x);

				// Update return variable
				bFtmp = false;

			}

			// Return variable
			return bFtmp;

		}

	}

}
